home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 7
/
Apprentice-Release7.iso
/
Source Code
/
Pascal
/
Applications
/
NIH Image 1.62b11
/
src
/
Lut.p
< prev
next >
Wrap
Text File
|
1996-08-30
|
54KB
|
2,228 lines
unit Lut;
{This file contains routines that deal with the video Look-Up Table(LUT).}
interface
uses
TYpes, Memory, QuickDraw, QuickDrawText, Packages, Menus, Events, Fonts, Scrap, ToolUtils,
Resources, Palettes, Printing, ColorPicker, Windows, Files, globals, Utilities, Graphics,
Dialogs;
function GetPseudoColorIndex: integer;
function isGrayScaleLUT: boolean;
procedure DoMouseDownInLUT (event: EventRecord);
procedure DoCopyColor;
procedure PasteColor;
procedure ShowRGBValues (index: integer);
procedure InvertPalette;
procedure FindPoints (var x1, y1, x2, y2: integer);
procedure UpdateMap;
procedure ResetGraymap;
procedure DrawMap;
procedure DoMouseDownInMap;
procedure EnableThresholding (level: integer);
procedure DisableThresholding;
procedure DrawLUT;
procedure UpdateLUT;
procedure LoadColorTable (theColorTable: CTabHandle);
function LoadCLUTResource (id: integer): boolean;
procedure GetLookupTable (var table: LookupTable);
procedure RedrawLUTWindow;
procedure DrawDensitySlice (OptionKey: boolean);
procedure SelectLutTool;
procedure EnableDensitySlice;
procedure SetupPseudocolor;
procedure DoImportLut (fname: str255; vnum: integer);
procedure OpenColorTable (fname: str255; RefNum: integer);
procedure ImportPalette (FileType: OSType; fname: str255; vnum: integer);
procedure GetColorTable (id: integer);
procedure GetLutResource (id: integer);
procedure DrawScale;
procedure MakeSpectrum;
function GetColorTableItem (ctab: ColorTableType): integer;
procedure SwitchColorTables (item: integer; update: boolean);
procedure InitPaletteHeader (var hdr: PaletteHeader);
procedure ResetMap;
procedure DoLutOptions;
function SetupMask: boolean;
procedure PutLineUsingMask (h, v, count: integer; var line: LineType);
procedure ApplyTable (var table: LookupTable);
procedure FixColors;
implementation
function GetPseudoColorIndex: integer;
var
index: integer;
begin
with info^ do begin
index := trunc((nColors) * (ForegroundIndex - ColorStart) / (ColorEnd - ColorStart + 1));
if index < 0 then
index := 0;
if index > (nColors - 1) then
index := nColors - 1;
GetPseudoColorIndex := index;
end;
end;
procedure UpdateLUT;
var
MaxStart, i, v, index, last: integer;
inc, sIndex: LongInt;
begin
with info^ do begin
sIndex := 0;
if ColorEnd > ColorStart then
inc := nColors * 10000 div (ColorEnd - ColorStart)
else
inc := 2560000;
if ColorStart < 0 then
sIndex := -ColorStart * Inc
else
sIndex := 0;
last := nColors - 1;
for i := 0 to 255 do
with cTable[i].rgb do begin
if (i < ColorStart) or (i > ColorEnd) then begin
if i < ColorStart then
cTable[i].rgb := FillColor1
else
cTable[i].rgb := FillColor2;
end
else begin
index := sIndex div 10000;
if index > last then
index := last;
Red := bsl(band(RedLUT[index],255), 8);
Green := bsl(band(GreenLUT[index],255), 8);
Blue := bsl(band(BlueLUT[index],255), 8);
sIndex := sIndex + inc;
end;
end; {for}
if ColorStart = ColorEnd then
cTable[ColorStart].rgb := FillColor2
else
Thresholding := false;
LoadLUT(cTable);
IdentityFunction := false;
end;
end;
function GetVLoc: integer;
var
loc: point;
vloc: integer;
begin
GetMouse(loc);
vloc := loc.v;
if vloc > 255 then
vloc := 255;
if vloc <= 0 then
vloc := 0;
GetVLoc := vloc;
end;
procedure GetNewColor (var color: RGBColor);
var
where: point;
inRGBColor, OutRGBColor: RGBColor;
begin
inRGBColor := color;
outRGBColor := color;
where.h := 0;
where.v := 0;
InitCursor;
if GetColor(where, 'Pick a new color...', inRGBColor, outRGBColor) then
color := outRGBColor;
end;
procedure EditPseudoColors;
var
where: point;
inRGBColor, OutRGBColor: RGBColor;
index, mloc: integer;
begin
SetupLUTUndo;
with info^ do begin
SetPort(LUTWindow);
mloc := getvloc;
if mloc < ColorStart then begin
GetNewColor(FillColor1);
UpdateLUT;
exit(EditPseudoColors);
end;
if mloc > ColorEnd then begin
GetNewColor(FillColor2);
UpdateLUT;
exit(EditPseudoColors);
end;
index := GetPseudoColorIndex;
with inRGBColor do begin
red := bsl(RedLUT[index], 8);
green := bsl(GreenLUT[index], 8);
blue := bsl(BlueLUT[index], 8);
end;
outRGBColor := inRGBColor;
where.h := 0;
where.v := 0;
InitCursor;
if GetColor(where, 'Pick a color, any color...', inRGBColor, outRGBColor) then begin
with outRGBColor do begin
RedLUT[index] := bsr(red, 8);
GreenLUT[index] := bsr(green, 8);
BlueLUT[index] := bsr(blue, 8);
end;
changes := true;
end;
ColorTable := CustomTable;
LutMode := PseudoColor;
UpdateLUT;
end; {with}
end;
function EditSliceColor: boolean;
var
where: point;
inRGBColor, OutRGBColor: RGBColor;
vloc: integer;
begin
SetPort(LUTWindow);
vloc := getvloc;
if (vloc >= SliceStart) and (vloc <= SliceEnd) then begin
GetNewColor(SliceColor);
DrawDensitySlice(false);
EditSliceColor := true
end
else
EditSliceColor := false;
end;
procedure ShowLUTValues (tStart, tEnd: integer);
var
tPort: GrafPtr;
value: extended;
range, NewMin, NewMax: LongInt;
begin
with info^ do begin
GetPort(tPort);
SetPort(InfoWindow);
TextSize(9);
TextFont(Monaco);
TextMode(SrcCopy);
MoveTo(xValueLoc, InfoVStart);
if DataType <> EightBits then begin
range := CurrentMax - CurrentMin;
if tEnd < 255 then
NewMin := CurrentMin + round(((255 - tEnd) / 255.0) * range)
else
NewMin := CurrentMin;
DrawLong(NewMin);
DrawString(' ');
MoveTo(xValueLoc, InfoVStart + 10);
if tStart > 0 then
NewMax := CurrentMax - round((tStart / 255.0) * range)
else
NewMax := CurrentMax;
DrawLong(NewMax);
DrawString(' ');
SetPort(tPort);
exit(ShowLUTValues);
end;
if fit <> uncalibrated then begin
if tStart >= 0 then
value := cvalue[tStart]
else
value := cvalue[0];
DrawReal(value, 5, 2);
DrawString(' (');
DrawReal(tStart, 3, 0);
DrawString(')');
end
else
DrawReal(tStart, 3, 0);
DrawString(' ');
MoveTo(xValueLoc, InfoVStart + 10);
if fit <> uncalibrated then begin
if tEnd <= 255 then
value := cvalue[tEnd]
else
value := cvalue[255];
DrawReal(value, 5, 2);
DrawString(' (');
DrawReal(tEnd, 3, 0);
DrawString(')');
end
else
DrawReal(tEnd, 3, 0);
DrawString(' ');
SetPort(tPort);
end;
end;
procedure ShowRGBValues (index: integer);
var
tPort: GrafPtr;
vloc: integer;
begin
with info^ do begin
GetPort(tPort);
SetPort(InfoWindow);
TextSize(9);
TextFont(Monaco);
TextMode(SrcCopy);
vloc := InfoVStart;
MoveTo(xValueLoc, vloc);
DrawLong(index);
DrawString(' ');
if Info^.fit <> uncalibrated then begin
vloc := vloc + 10;
MoveTo(xValueLoc, vloc);
DrawReal(cvalue[index], 1, precision);
DrawString(' ');
end;
vloc := vloc + 10;
MoveTo(xValueLoc, vloc);
DrawRGB(index);
DrawString(' ');
SetPort(tPort);
end;
end;
procedure FindPoints (var x1, y1, x2, y2: integer);
begin
with info^ do begin
if ColorStart >= 0 then begin
x1 := ColorStart;
y1 := 0;
end
else begin
x1 := 0;
if ColorEnd > ColorStart then
y1 := -ColorStart * 255 div (ColorEnd - ColorStart)
else
y1 := 0;
end;
if ColorEnd <= 255 then begin
x2 := ColorEnd;
y2 := 255;
end
else begin
x2 := 255;
if ColorEnd > ColorStart then
y2 := 255 * (255 - ColorStart) div (ColorEnd - ColorStart)
else
y2 := 255;
end;
end;
end;
procedure UpdateMap;
var
r: rect;
x, y, i, h1, h2, h3, v1, v2, v3, dx, dy: integer;
xcenter, ycenter, brightness, islope, thumb: integer;
width, max: integer;
table: LookupTable;
hrect: rect;
slope: extended;
area, value, sum: LongInt;
p1x, p1y, p2x, p2y: integer;
begin
with info^ do begin
FindPoints(p1x, p1y, p2x, p2y);
SetPort(MapWindow);
PenNormal;
EraseRect(MapRect2);
FrameRect(MapRect1);
if LutMode = CustomGrayscale then begin
GetLookupTable(table);
MoveTo(gmRectLeft, gmRectBottom - 1);
for i := 0 to 63 do begin
x := gmRectLeft + i;
y := gmRectBottom - table[i * 4] div 4 - 1;
LineTo(x, y);
end;
EraseRect(gmSlide1i);
EraseRect(gmSlide2i);
if ScreenDepth <> 8 then begin
DrawLut;
UpdatePicWindow;
end;
exit(UpdateMap);
end;
h1 := gmRectLeft + p1x div 4;
v1 := gmRectBottom - 1 - (p1y div 4);
h2 := gmRectLeft + p2x div 4;
v2 := gmRectBottom - 1 - (p2y div 4);
MoveTo(gmRectLeft, gmRectBottom - 1);
LineTo(h1, v1);
LineTo(h2, v2);
LineTo(gmRectRight - 1, gmRectTop);
SetRect(hrect, h1 - 1, v1 - 1, h1 + 2, v1 + 2);
PaintRect(hrect); {First handle}
SetRect(hrect, h2 - 1, v2 - 1, h2 + 2, v2 + 2);
PaintRect(hrect); {Last handle}
dx := p2x - p1x;
dy := p2y - p1y;
xcenter := p1x + dx div 2;
ycenter := p1y + dy div 2;
h3 := gmRectLeft + xcenter div 4;
v3 := gmRectBottom - 1 - (ycenter div 4);
SetRect(hrect, h3 - 1, v3 - 1, h3 + 2, v3 + 2);
PaintRect(hrect); {Center handle}
thumb := gmSlideHeight - 2;
max := gmSlideWidth - thumb - 2;
width := ColorEnd - ColorStart;
brightness := trunc(max * ((ColorStart + width) / (width + 255)));
with gmSlide1 do
SetRect(hrect, left + brightness + 1, top + 1, left + brightness + thumb + 1, top + thumb + 1);
EraseRect(gmSlide1i);
PaintRect(hrect); {Thumb for contrast control}
if dx <> 0 then
slope := dy / dx
else
slope := 1000.0;
if slope > 1.0 then begin
if dy <> 0 then
slope := 2.0 - dx / dy
else
slope := 2.0;
end;
islope := trunc(slope * 0.5 * (gmSlideWidth - thumb - 2.0));
with gmSlide2 do
SetRect(hrect, left + islope + 1, top + 1, left + islope + thumb + 1, top + thumb + 1);
EraseRect(gmSlide2i);
PaintRect(hrect); {Thumb for contrast control}
if ScreenDepth <> 8 then begin
if ScreenDepth > 2 then
DrawLut;
UpdatePicWindow;
end;
end;
end;
procedure UpdateThreshold;
var
level: integer;
begin
DrawLabels('Thresh:', '', '');
ShowMessage('');
with info^ do
repeat
SetPort(LUTWindow);
level := GetVLoc;
if level <= 255 then begin
ColorStart := level;
ColorEnd := level;
UpdateLUT;
UpdateMap;
end;
Show1Value(level, NoValue);
until not Button;
end;
procedure UpdateDensitySlice;
var
mloc, saveloc, width, delta: integer;
adjust: (lower, upper, both);
begin
DrawLabels('Lower:', 'Upper:', '');
SetPort(LUTWindow);
mloc := getvloc;
saveloc := mloc;
width := SliceEnd - SliceStart + 1;
adjust := lower;
if mloc > (SliceStart + width div 4) then
adjust := both;
if mloc > (SliceEnd - width div 4) then
adjust := upper;
if (SliceStart = SliceEnd) and (abs(mloc - SliceStart) <= 2) and (SliceStart > 1) and (SliceEnd < 254) then
adjust := both;
while button do begin
width := SliceEnd - SliceStart + 1;
mloc := getvloc;
delta := mloc - saveloc;
saveloc := mloc;
case adjust of
lower: begin
SliceStart := mloc;
if SliceStart < 1 then
SliceStart := 1;
if SliceStart > SliceEnd then
SliceStart := SliceEnd;
end;
upper: begin
SliceEnd := mloc;
if SliceEnd > 254 then
SliceEnd := 254;
if SliceEnd < SliceStart then
SliceEnd := SliceStart;
end;
both: begin
if mloc <= 1 then begin
SliceStart := 1;
SliceEnd := width;
end
else if mloc >= 254 then begin
SliceEnd := 254;
SliceStart := 254 - width + 1;
end
else if ((SliceStart + delta) >= 1) and ((SliceEnd + delta) <= 254) then begin
SliceStart := SliceStart + delta;
SliceEnd := SliceEnd + delta;
end;
end;
end; {case}
DrawDensitySlice(OptionKeyDown);
ShowLUTValues(SliceStart, SliceEnd);
end; {while}
DrawDensitySlice(false)
end;
procedure EditExtraColors (entry: integer);
var
where: point;
inRGBColor, OutRGBColor: RGBColor;
begin
if (entry <> WhiteIndex) and (entry <> BlackIndex) then begin
inRGBColor := ExtraColors[entry];
outRGBColor := inRGBColor;
where.h := 0;
where.v := 0;
InitCursor;
if GetColor(where, 'Pick a color, any color...', inRGBColor, outRGBColor) then
with info^ do begin
ExtraColors[entry] := OutRGBColor;
changes := true;
LoadLUT(cTable);
end
end
else
PutError('Sorry, but you can not edit white or black.');
end;
function GetColorFromLUT (DoubleClick: boolean): integer;
var
mloc, color, i: integer;
loc: point;
begin
SetPort(LUTWindow);
GetMouse(loc);
if loc.v > 255 then begin
color := 0;
for i := 1 to nExtraColors + 2 do
if PtInRect(loc, ExtraColorsRect[i]) then
Color := ExtraColorsEntry[i];
if DoubleClick then
EditExtraColors(color);
GetColorFromLUT := color;
end
else
GetColorFromLUT := loc.v;
end;
function isGrayScaleLUT: boolean;
var
i: integer;
GrayScaleLUT: boolean;
begin
with info^ do begin
GrayscaleLUT := true;
i := 0;
repeat
with cTable[i].rgb do
GrayscaleLUT := GrayscaleLUT and (red = green) and (green = blue);
i := i + 1;
until (i = 256) or not GrayscaleLUT;
isGrayScaleLUT := GrayScaleLUT;
end;
end;
procedure SetupPseudocolor;
var
i: integer;
begin
with info^ do begin
DisableDensitySlice;
Thresholding := false;
for i := 1 to 254 do
with cTable[i].rgb do begin
RedLUT[i] := band(bsr(red, 8), 255);
GreenLUT[i] := band(bsr(green, 8), 255);
BlueLUT[i] := band(bsr(blue, 8), 255);
end;
RedLUT[0] := RedLUT[1];
GreenLUT[0] := GreenLUT[1];
BlueLUT[0] := BlueLUT[1];
RedLUT[255] := RedLUT[254];
GreenLUT[255] := GreenLUT[254];
BlueLUT[255] := BlueLUT[254];
nColors := 256;
ColorStart := 0;
ColorEnd := 255;
FillColor1 := ctable[1].rgb;
FillColor2 := ctable[254].rgb;
InvertedColorTable := false;
end;
end;
procedure ShowLabels;
begin
with info^ do
if DataType <> EightBits then
DrawLabels('Min:', 'Max:', '')
else
DrawLabels('Lower:', 'Upper:', '');
end;
procedure AdjustLUT;
const
MinWidth = 8;
var
mloc, saveloc, width, delta, cstart, cend: integer;
adjust: (lower, upper, both);
loc: point;
begin
with info^ do begin
SetPort(LUTWindow);
SetupLutUndo;
ShowLabels;
mloc := getvloc;
saveloc := mloc;
cstart := ColorStart;
if cstart < 0 then
cstart := 0;
cend := ColorEnd;
if cend > 255 then
cend := 255;
width := cend - cstart + 1;
adjust := lower;
if mloc > (cstart + width div 4) then
adjust := both;
if mloc > (cend - width div 4) then
adjust := upper;
while button do begin
SetPort(LUTWindow);
GetMouse(loc);
mloc := loc.v;
delta := mloc - saveloc;
saveloc := mloc;
case adjust of
lower: begin
ColorStart := mloc;
cend := ColorEnd;
if cend > 255 then
cend := 255;
if ColorStart > (cend - MinWidth) then
ColorStart := cend - MinWidth;
end;
upper: begin
ColorEnd := mloc;
cstart := ColorStart;
if cstart < 0 then
cstart := 0;
if ColorEnd < (cstart + MinWidth) then
ColorEnd := cstart + MinWidth;
end;
both:
if (mloc >= 0) and (mloc <= 255) then begin
ColorStart := ColorStart + delta;
ColorEnd := ColorEnd + delta;
end;
end;
UpdateLUT;
UpdateMap;
ShowLUTValues(ColorStart, ColorEnd);
end;
end; {with info}
end;
procedure RotateLUT;
var
vstart, i, j, delta: integer;
loc: point;
tempRed, tempGreen, tempBlue: LutArray;
begin
with info^ do begin
SetPort(LUTWindow);
GetMouse(loc);
vstart := loc.v;
SetupPseudocolor;
ColorTable := CustomTable;
repeat
GetMouse(loc);
delta := vstart - loc.v;
for i := 1 to 254 do begin {0 is resevred for white and 255 for black}
j := i + delta;
if j > 254 then
j := j - 254;
if j > 254 then
j := 254;
if j < 1 then
j := j + 254;
if j < 1 then
j := 1;
tempRed[i] := RedLut[j];
tempGreen[i] := GreenLut[j];
tempBlue[i] := BlueLut[j];
end;
RedLut := tempRed;
GreenLut := tempGreen;
BlueLut := tempBlue;
UpdateLUT;
if ScreenDepth <> 8 then begin
DrawLut;
UpdatePicWindow;
end;
vstart := loc.v;
until not button;
end;
end;
procedure DoMouseDownInLUT (event: EventRecord);
var
color: integer;
DoubleClick: boolean;
begin
with info^ do begin
if CurrentTool = PickerTool then
DoubleClick := (TickCount - LutTime) < GetDblTime
else
DoubleClick := false;
LutTime := TickCount;
if (CurrentTool <> LutTool) and (CurrentTool <> Wand) then begin
color := GetColorFromLUT(DoubleClick);
if (CurrentTool = eraser) or OptionKeyDown then
SetBackgroundColor(color)
else
SetForegroundColor(color);
if not DoubleClick then
exit(DoMouseDownInLUT);
end;
if Thresholding then begin
UpdateThreshold;
exit(DoMouseDownInLUT)
end;
if DoubleClick then begin
if DensitySlicing and (CurrentTool = PickerTool) then begin
if EditSliceColor then
exit(DoMouseDownInLUT);
end;
if CurrentTool = PickerTool then begin
EditPseudoColors;
exit(DoMouseDownInLUT)
end;
end; {if DoubleClick}
if ((CurrentTool = LutTool) or (CurrentTool = Wand)) and DensitySlicing then begin
UpdateDensitySlice;
exit(DoMouseDownInLUT);
end;
if OptionKeyDown then
RotateLUT
else
AdjustLUT;
end; {with}
end;
procedure DoCopyColor;
begin
with info^ do begin
if ForegroundIndex = WhiteIndex then begin
ClipboardColor := WhiteRGB;
exit(DoCopyColor);
end;
if ForegroundIndex = BlackIndex then begin
ClipboardColor := BlackRGB;
exit(DoCopyColor);
end;
with cTable[ForegroundIndex].rgb do begin
ClipboardColor.red := red;
ClipboardColor.green := green;
ClipboardColor.blue := blue;
end;
WhatsOnClip := AColor;
ClipTextInBuffer := false;
end;
end;
procedure PasteColor;
var
CurrentColorIndex: integer;
begin
with info^ do begin
if CurrentTool = PickerTool then begin
if ForegroundIndex < ColorStart then begin
FillColor1 := ClipboardColor;
UpdateLUT;
exit(PasteColor);
end;
if ForegroundIndex > ColorEnd then begin
FillColor2 := ClipboardColor;
UpdateLUT;
exit(PasteColor);
end;
CurrentColorIndex := GetPseudoColorIndex;
with ClipboardColor do begin
RedLUT[CurrentColorIndex] := bsr(red, 8);
GreenLUT[CurrentColorIndex] := bsr(green, 8);
BlueLUT[CurrentColorIndex] := bsr(blue, 8);
end;
ColorTable := CustomTable;
UpdateLUT;
end
else
beep;
end;
end;
procedure InvertPalette;
var
TempRed, TempGreen, TempBlue: LutArray;
i, LastColor: integer;
TempTable: MyCSpecArray;
TempFill: rgbColor;
begin
DisableDensitySlice;
DisableThresholding;
with info^ do begin
TempRed := RedLUT;
TempGreen := GreenLUT;
TempBlue := BlueLUT;
LastColor := ncolors - 1;
for i := 0 to LastColor do begin
RedLUT[i] := TempRed[LastColor - i];
GreenLUT[i] := TempGreen[LastColor - i];
BlueLUT[i] := TempBlue[LastColor - i];
end;
TempFill := FillColor1;
FillColor1 := FillColor2;
FillColor2 := TempFill;
InvertedColorTable := not InvertedColorTable;
IdentityFunction := false;
end;
end;
procedure DrawMap;
var
x, y, i: integer;
table: LookupTable;
begin
SetPort(MapWindow);
PenNormal;
TextFont(Geneva);
TextSize(9);
with gmSlide1 do
MoveTo(left - 6, bottom);
DrawChar('B');
with gmSlide2 do
MoveTo(left - 6, bottom);
DrawChar('C');
FrameRect(gmSlide1);
FrameRect(gmSlide2);
FrameRect(gmIcon1);
FrameRect(gmIcon2);
with gmIcon1 do begin
MoveTo(left, top + 10);
LineTo(left + 5, top + 10);
LineTo(left + 12, top + 3);
LineTo(left + gmIconWidth - 1, top + 3);
end;
with gmIcon2 do begin
MoveTo(left, top + 10);
LineTo(left + gmIconWidth div 2, top + 10);
LineTo(left + gmIconWidth div 2, top + 3);
LineTo(left + gmIconWidth - 1, top + 3);
end;
UpdateMap;
GrayMapReady := true;
end;
procedure ResetGrayMap;
var
i: integer;
begin
with info^ do begin
DisableDensitySlice;
for i := 0 to 255 do begin
RedLut[i] := 255 - i;
GreenLut[i] := 255 - i;
BlueLut[i] := 255 - i;
end;
FillColor1 := WhiteRGB;
FillColor2 := BlackRGB;
ColorStart := 0;
ColorEnd := 255;
nColors := 256;
ColorTable := CustomTable;
LUTMode := Grayscale;
UpdateLUT;
if GrayMapReady then
UpdateMap;
IdentityFunction := true;
InvertedColorTable := false;
end;
end;
procedure AdjustBrightness;
var
loc, max, thumb, xcenter, ycenter, width: integer;
p: point;
begin
with info^ do begin
thumb := gmSlideHeight - 2;
max := gmSlideWidth - thumb - 2;
width := ColorEnd - ColorStart;
ShowLabels;
repeat
GetMouse(p);
loc := p.h - gmSlide1.left - 2;
if loc < 0 then
loc := 0;
if loc > max then
loc := max;
ColorStart := -width + round((width + 255) * (loc / max));
ColorEnd := ColorStart + width;
UpdateLUT;
UpdateMap;
ShowLUTValues(ColorStart, ColorEnd);
until not button;
IdentityFunction := false;
end; {with}
end;
procedure AdjustContrast;
var
p: point;
loc, max, HalfMax, thumb: integer;
slope, center: extended;
begin
with info^ do begin
thumb := gmSlideHeight - 2;
max := gmSlideWidth - thumb - 2;
HalfMax := max div 2;
center := ColorStart + (ColorEnd - ColorStart) / 2.0;
ShowLabels;
repeat
GetMouse(p);
loc := p.h - gmSlide2.left - 2;
if loc < 0 then
loc := 0;
if loc > max then
loc := max;
if loc <= HalfMax then
slope := loc / HalfMax
else if loc < max then
slope := HalfMax / (max - loc)
else
slope := 1000.0;
if slope > 0.0 then begin
ColorStart := round(center - 127.5 / slope);
ColorEnd := round(center + 127.5 / slope);
end
else begin
ColorStart := round(center - MaxColor);
ColorEnd := round(center + MaxColor);
end;
if ColorEnd < 0 then
ColorEnd := 0;
if ColorStart > 255 then
ColorStart := 255;
UpdateLUT;
UpdateMap;
ShowLUTValues(ColorStart, ColorEnd);
until not button;
IdentityFunction := false;
end; {with}
end;
procedure ConvertMouseToXY (p: point; var x, y: integer);
begin
x := (p.h - gmRectLeft) * 4;
if x < 0 then
x := 0;
if x > 255 then
x := 255;
y := (gmRectBottom - p.v) * 4;
if y < 0 then
y := 0;
if y > 255 then
y := 255;
end;
procedure DoFreehandEditing;
var
p: point;
x1, x2, y, i: integer;
FirstTime: boolean;
begin
with info^ do begin
LUTMode := CustomGrayscale;
SetPort(MapWindow);
FirstTime := true;
while button do begin
x1 := x2;
GetMouse(p);
ConvertMouseToXY(p, x2, y);
if x2 > 252 then
x2 := 252;
if FirstTime then begin
x1 := x2;
FirstTime := false;
end;
if x2 >= x1 then
for i := x1 to x2 + 3 do
with cTable[i].rgb do begin
red := bsl(255 - y, 8);
green := bsl(255 - y, 8);
blue := bsl(255 - y, 8);
end
else
for i := x1 + 3 downto x2 do
with cTable[i].rgb do begin
red := bsl(255 - y, 8);
green := bsl(255 - y, 8);
blue := bsl(255 - y, 8);
end;
DrawMap;
LoadLUT(cTable);
if ScreenDepth <> 8 then UpdatePicWindow;
end;
if not isGrayscaleLut then
LutMode := ColorLut;
end;
end;
procedure DisableThresholding;
begin
with info^ do
if thresholding then begin
ColorStart := SaveColorStart;
ColorEnd := SaveColorEnd;
FillColor1 := SaveFill1;
FillColor2 := SaveFill2;
UpdateLut;
UpdateMap;
Thresholding := false;
end;
end;
procedure EnableThresholding (level: integer);
begin
with info^ do begin
if not thresholding then begin
SaveColorStart := ColorStart;
SaveColorEnd := ColorEnd;
SaveFill1 := FillColor1;
SaveFill2 := FillColor2;
end;
ColorStart := level;
ColorEnd := level;
FillColor1 := WhiteRGB;
FillColor2 := BlackRGB;
UpdateLut;
UpdateMap;
Thresholding := true;
if not macro then
SelectLutTool;
end;
end;
procedure ResetMap;
begin
with info^ do begin
ColorStart := 0;
ColorEnd := 255;
if Thresholding then begin
FillColor1 := SaveFill1;
FillColor2 := SaveFill2;
end;
IdentityFunction := LutMode = Grayscale;
UpdateLUT;
UpdateMap;
end;
end;
procedure DoMouseDownInMap;
var
r: rect;
x, y, p1Dist, p2Dist: integer;
mode: (StartPoint, EndPoint, Brightness, AdjustThreshold);
p: point;
pressed: boolean;
x1, y1, x2, y2: integer;
xintercept: integer;
deltax, deltay, width: LongInt;
procedure DoFixup;
begin
with info^ do
if ((x1 = 0) and (x2 = 0)) or ((x1 = 255) and (x2 = 255)) then begin
y1 := 0;
y2 := 255;
end;
end;
begin
with info^ do begin
DisableDensitySlice;
if OptionKeyDown then begin
DoFreehandEditing;
exit(DoMouseDownInMap);
end;
if LUTMode = CustomGrayscale then
ResetGrayMap;
FindPoints(x1, y1, x2, y2);
SetPort(MapWindow);
GetMouse(p);
if PtInRect(p, gmIcon1) then begin
InvertRect(gmIcon1);
pressed := true;
while Button and pressed do begin
GetMouse(p);
if not PtInRect(p, gmIcon1) then begin
InvertRect(gmIcon1);
pressed := false;
end;
end;
repeat
until not button;
if pressed then begin
InvertRect(gmIcon1);
ResetMap;
exit(DoMouseDownInMap)
end;
end;
if PtInRect(p, gmIcon2) then begin
InvertRect(gmIcon2);
pressed := true;
while Button and pressed do begin
GetMouse(p);
if not PtInRect(p, gmIcon2) then begin
InvertRect(gmIcon2);
pressed := false;
end;
end;
repeat
until not button;
if pressed then begin
InvertRect(gmIcon2);
if Thresholding then
DisableThresholding
else
EnableThresholding(128);
exit(DoMouseDownInMap)
end;
end;
if PtInRect(p, gmSlide1) then
AdjustBrightness;
if PtInRect(p, gmSlide2) then
AdjustContrast;
if p.v > (gmRectBottom + 4) then begin
if not thresholding and ((x2 - x1) <= 1) then begin
thresholding := true;
SaveFill1 := FillColor1;
SaveFill2 := FillColor2;
end;
exit(DoMouseDownInMap);
end;
if LutMode = CustomGrayscale then
LutMode := Grayscale;
GetMouse(p);
ConvertMouseToXY(p, x, y);
if (x <= 24) or (y <= 32) then
mode := StartPoint
else if (x >= 224) or (y >= 232) then
mode := EndPoint
else if thresholding then
mode := AdjustThreshold
else
mode := brightness;
if mode = AdjustThreshold then
DrawLabels('Thresh:', '', '')
else
ShowLabels;
repeat
case mode of
StartPoint: begin
if thresholding then begin
FillColor1 := SaveFill1;
FillColor2 := SaveFill2;
end;
if x > y then
y := 0
else
x := 0;
x1 := x;
if x1 > x2 then
x2 := x1;
y1 := y;
if y1 > y2 then
y2 := y1;
DoFixUp;
end;
EndPoint: begin
if thresholding then begin
FillColor1 := SaveFill1;
FillColor2 := SaveFill2;
end;
if x > y then
x := 255
else
y := 255;
x2 := x;
if x2 < x1 then
x1 := x2;
y2 := y;
if y2 < y1 then
y1 := y2;
DoFixUp;
end;
Brightness: begin
deltax := x2 - x1;
deltay := y2 - y1;
if deltax = 0 then begin
x1 := x;
y1 := 0;
x2 := x;
y2 := 255;
end
else if deltay = 0 then begin
x1 := 0;
y1 := y;
x2 := 255;
y2 := y;
end
else begin
x1 := x - y * deltax div deltay;
xIntercept := x1;
y1 := 0;
if x1 < 0 then begin
y1 := -deltay * x1 div deltaX;
x1 := 0;
end;
y2 := 255;
x2 := 255 * deltax div deltay;
if xIntercept < 0 then
x2 := x2 + xIntercept
else
x2 := x2 + x1;
if x2 > 255 then begin
y2 := 255 - (x2 - 255) * deltay div deltax;
x2 := 255;
end;
end;
if x2 < 1 then
x2 := 1;
if y2 < 1 then
y2 := 1;
if x1 > 254 then
x1 := 254;
if y1 > 254 then
y1 := 254;
end;
AdjustThreshold: begin
x1 := x;
y1 := 0;
x2 := x;
y2 := 255;
end;
end; {case}
{showmessage(concat(long2str(x1), ' ', long2str(y1), ' ', long2str(x2), ' ', long2str(y2), crStr, long2str(ColorStart), ' ', long2str(ColorEnd)));}
width := x2 - x1;
if y1 = 0 then
ColorStart := x1
else begin
if (y2 > y1) then
ColorStart := -width * y1 div (y2 - y1)
else
ColorStart := -MaxColor;
end;
if y2 = 255 then
ColorEnd := x2
else begin
if (y2 > y1) then
ColorEnd := 255 + width * (255 - y2) div ((y2 - y1))
else
ColorEnd := MaxColor;
end;
UpdateLUT;
UpdateMap;
if thresholding then
Show1Value(ColorStart, NoValue)
else
ShowLUTValues(ColorStart, ColorEnd);
GetMouse(p);
ConvertMouseToXY(p, x, y);
until not Button;
IdentityFunction := false;
if not thresholding and ((x2 - x1) <= 1) then begin
thresholding := true;
SaveFill1 := FillColor1;
SaveFill2 := FillColor2;
end;
end; {with info}
end;
procedure DrawLUT;
var
tPort: GrafPtr;
h, v, i: integer;
begin
GetPort(tPort);
SetPort(LUTWindow);
with LutWindow^ do begin
for v := 0 to 255 do begin
SetFColor(v);
MoveTo(0, v);
LineTo(cwidth, v)
end;
for i := 1 to nExtraColors + 2 do begin
SetFColor(ExtraColorsEntry[i]);
PaintRect(ExtraColorsRect[i]);
end;
TextFont(Geneva);
TextSize(9);
with ExtraColorsRect[1] do
MoveTo(left + 3, bottom - 1);
SetFColor(BlackIndex);
DrawString('white');
with ExtraColorsRect[2] do
MoveTo(left + 4, bottom - 1);
InvertRect(ExtraColorsRect[2]);
DrawString('black');
InvertRect(ExtraColorsRect[2]);
end;
SetPort(tPort);
end;
function LoadPP2Palette: boolean;
{Loads COLR resource from PixelPaint 2.0 palette file.}
var
i: integer;
size: LongInt;
h: Handle;
PPColorTable: record
ctSize: INTEGER;
table: array[0..255] of RGBColor;
end;
begin
h := GetResource('COLR', 999);
size := GetHandleSize(handle(h));
if (ResError = NoErr) and (size = 1538) then
with info^ do begin
BlockMove(handle(h)^, @PPColorTable, SizeOf(PPColorTable));
with PPColorTable do begin
for i := 0 to 255 do
cTable[i].rgb := table[i];
end;
LoadLUT(cTable);
LutMode := ColorLut;
SetupPseudocolor;
IdentityFunction := false;
LoadPP2Palette := true;
end
else
LoadPP2Palette := false;
if h <> nil then
DisposeHandle(h);
end;
procedure LoadColorTable (theColorTable: CTabHandle);
const
ExpectedSize = 2056;
var
size: LongInt;
MyColorTable: record
ctSeed: LONGINT;
transIndex: INTEGER;
ctSize: INTEGER;
ctTable: MyCSpecArray;
end;
begin
size := GetHandleSize(handle(theColorTable));
if size < ExpectedSize then
exit(LoadColorTable);
if size > ExpectedSize then
Size := ExpectedSize;
BlockMove(handle(theColorTable)^, @MyColorTable, size);
LoadLUT(MyColorTable.ctTable);
with info^ do begin
cTable := MyColorTable.ctTable;
LutMode := ColorLut;
IdentityFunction := false;
end;
SetupPseudocolor;
end;
function LoadCLUTResource;{(id:integer):boolean}
const
ExpectedSize = 2056;
var
Size: LongInt;
h: cTabHandle;
begin
DisableDensitySlice;
h := GetCTable(id);
size := GetHandleSize(handle(h));
if (ResError <> NoErr) or (size < ExpectedSize) then begin
LoadCLUTResource := false;
if id = PixelpaintID then begin
if LoadPP2Palette then
LoadCLUTResource := true;
end;
if h <> nil then
DisposeCTable(h);
exit(LoadCLUTResource)
end;
LoadColorTable(h);
DisposeCTable(h);
LoadCLUTResource := true;
end;
procedure GetLookupTable;{(VAR table:LookupTable)}
var
i, r, g, b: integer;
GrayscaleImage: boolean;
begin
with info^ do begin
if DensitySlicing then begin
for i := 0 to 255 do
if (i >= SliceStart) and (i <= SliceEnd) then begin
if ThresholdToForeground then
table[i] := ForegroundIndex
else
table[i] := i
end
else begin
if NonThresholdToBackground then
table[i] := BackgroundIndex
else
table[i] := i
end;
DisableDensitySlice;
exit(GetLookupTable);
end;
if (LutMode = GrayScale) or (LutMode = CustomGrayscale) then
for i := 0 to 255 do
table[i] := 255 - BSR(cTable[i].RGB.red, 8)
else begin
table[0] := 0;
for i := 1 to 254 do
with cTable[i].RGB do
table[i] := 255 - trunc(band(bsr(red, 8), 255) * 0.3 + band(bsr(green, 8), 255) * 0.59 + band(bsr(blue, 8), 255) * 0.11);
table[255] := 255;
end;
end; {with}
end;
procedure RedrawLUTWindow;
begin
LoadLUT(info^.cTable);
cheight := 256 + (2 + nExtraColors) * ExtraColorsHeight;
SizeWindow(LUTWindow, cwidth, cheight, true);
if ScreenDepth <> 8 then
DrawLUT;
end;
procedure DrawDensitySlice (OptionKey: boolean);
var
i, tRed: integer;
begin
with info^ do begin
if OptionKey then begin
UndoLutChange;
if ScreenDepth <> 8 then begin
DrawLut;
UpdatePicWindow;
end;
exit(DrawDensitySlice);
end
else
for i := 0 to 255 do
if (i >= SliceStart) and (i <= SliceEnd) then
cTable[i].rgb := SliceColor
else
ctable[i].rgb := UndoInfo^.cTable[i].rgb;
LoadLUT(cTable);
if ScreenDepth <> 8 then begin
if ScreenDepth > 2 then
DrawLut;
UpdatePicWindow;
end;
end;
end;
procedure SelectLutTool;
var
tPort: GrafPtr;
begin
if (CurrentTool <> LutTool) and (CurrentTool <> Wand) then begin
GetPort(tPort);
SetPort(ToolWindow);
InvalRect(ToolRect[CurrentTool]);
InvalRect(ToolRect[LutTool]);
CurrentTool := LutTool;
isSelectionTool := false;
SetPort(tPort);
end;
end;
procedure EnableDensitySlice;
begin
if not DensitySlicing then begin
SetupLutUndo;
DrawDensitySlice(false);
DensitySlicing := true;
SelectLUTTool;
end;
end;
procedure DoImportLut (fname: str255; vnum: integer);
var
err: OSErr;
f, i,j,tRed: integer;
ByteCount: LongInt;
ImportedLUT: array[1..3] of packed array[0..255] of byte;
begin
DisableDensitySlice;
err := fsopen(fname, vNum, f);
ByteCount := 768;
err := fsRead(f, ByteCount, @ImportedLUT);
if err = NoErr then
with info^ do begin
for i := 0 to 255 do
with cTable[i], cTable[i].rgb do begin
value := 0;
red := bsl(band(ImportedLUT[1, i],255), 8);
green := bsl(band(ImportedLUT[2, i],255), 8);
blue := bsl(band(ImportedLUT[3, i],255), 8);
end;
LoadLUT(cTable);
SetupPseudocolor;
LutMode := PseudoColor;
IdentityFunction := false;
if isGrayScaleLUT then
info^.LutMode := CustomGrayScale;
UpdateLut;
UpdateMap;
end
else
beep;
err := fsClose(f);
end;
procedure OpenOldPalette (fname: str255; RefNum: integer);
{Opens palette files created by versions NIH Image earlier than 1.42.}
var
PaletteHeader: ColorArray;
err, f, ColorWidth: integer;
size: LongInt;
begin
DisableDensitySlice;
err := fsopen(fname, RefNum, f);
with info^ do begin
size := SizeOf(ColorArray);
err := fsread(f, size, @PaletteHeader);
nColors := PaletteHeader[0];
if nColors > MaxPseudocolors then
nColors := MaxPseudoColors;
ColorEnd := 255 - PaletteHeader[1];
ColorWidth := PaletteHeader[2];
ColorStart := ColorEnd - nColors * ColorWidth + 1;
if ColorStart < 0 then
ColorStart := 0;
FillColor1 := BlackRGB;
FillColor2 := BlackRGB;
err := fsread(f, size, @RedLut);
err := fsread(f, size, @GreenLut);
err := fsread(f, size, @BlueLut);
LutMode := PseudoColor;
InvertedColorTable := false;
end;
err := fsclose(f);
end;
procedure OpenNewPalette (fname: str255; RefNum: integer);
{Opens palette files created by versions of NIH Image later than 1.41.}
var
err, f: integer;
count: LongInt;
hdr: PaletteHeader;
begin
DisableDensitySlice;
err := fsopen(fname, RefNum, f);
with info^ do begin
count := SizeOf(PaletteHeader);
err := fsread(f, count, @hdr);
with hdr do begin
nColors := pnColors;
if nColors > 256 then
nColors := 256;
ColorStart := pColorStart;
ColorEnd := pColorEnd;
FillColor1 := pFill1;
FillColor2 := pFill2;
InvertedColorTable := false;
end;
count := nColors;
err := fsread(f, count, @RedLut);
count := nColors;
err := fsread(f, count, @GreenLut);
count := nColors;
err := fsread(f, count, @BlueLut);
LutMode := PseudoColor;
end;
err := fsclose(f);
end;
procedure OpenColorTable (fname: str255; RefNum: integer);
var
err: OSErr;
f: integer;
FileSize, count: LongInt;
id: packed array[1..4] of char;
begin
err := fsopen(fname, RefNum, f);
err := GetEOF(f, FileSize);
count := SizeOf(id);
err := fsread(f, count, @id);
err := fsclose(f);
if FileSize = 768 then
DoImportLut(fname, RefNum)
else if id = 'ICOL' then
OpenNewPalette(fname, RefNum)
else
OpenOldPalette(fname, RefNum);
UpdateLUT;
UpdateMap;
end;
procedure ImportPalette (FileType: OSType; fname: str255; vnum: integer);
var
RefNum: integer;
ok: boolean;
err: OSErr;
begin
err := SetVol(nil, vnum);
refNum := OpenResFile(fname);
if RefNum <> -1 then begin
if FileType = 'CLUT' then
ok := LoadClutResource(KlutzID)
else
ok := LoadClutResource(PixelPaintID); {Load PixelPaint or Canvas palette}
CloseResFile(RefNum);
if isGrayScaleLUT then begin
info^.LutMode := CustomGrayScale;
DrawMap;
end;
end;
end;
procedure InitPaletteHeader (var hdr: PaletteHeader);
var
i: integer;
begin
with hdr, info^ do begin
pID := 'ICOL';
pVersion := version;
pnColors := nColors;
pColorStart := ColorStart;
pColorEnd := ColorEnd;
pFill1 := FillColor1;
pFill2 := FillColor2;
for i := 1 to 4 do
pUnused[i] := 0;
end;
end;
procedure SaveLutResource;
{Saves the current color table as a CPAL resource}
var
id: integer;
canceled: boolean;
PalH: handle;
hdr: PaletteHeader;
p: ptr;
begin
with info^ do begin
id := GetInt('Resource ID', 1000, canceled);
if canceled then
exit(SaveLutResource);
PalH := GetResource('CPAL', id);
if GetHandleSize(PalH) > 0 then begin
RemoveResource(PalH);
DisposeHandle(PalH);
end;
InitPaletteHeader(hdr);
PalH := NewHandle(SizeOF(PaletteHeader) + nColors * 3);
p := PalH^;
BlockMove(@hdr, p, SizeOf(PaletteHeader));
p := ptr(ord4(p) + SizeOf(PaletteHeader));
BlockMove(@RedLut, p, nColors);
p := ptr(ord4(p) + nColors);
BlockMove(@GreenLut, p, nColors);
p := ptr(ord4(p) + nColors);
BlockMove(@BlueLut, p, nColors);
AddResource(PalH, 'CPAL', id, '');
WriteResource(PalH);
if ResError <> NoErr then
beep;
DisposeHandle(PalH);
end;
end;
procedure GetLutResource (id: integer);
var
LutH: handle;
hdr: PaletteHEader;
p: ptr;
begin
with info^ do begin
LutH := GetResource('CPAL', id);
if (ResError <> noErr) or (LutH = nil) then begin
beep;
if LutH <> nil then
ReleaseResource(LutH);
exit(GetLutResource)
end;
p := LutH^;
BlockMove(p, @hdr, SizeOf(PaletteHeader));
with hdr do begin
if pID <> 'ICOL' then begin
beep;
ReleaseResource(LutH);
exit(GetLutResource);
end;
nColors := pnColors;
if nColors > 256 then
nColors := 256;
ColorStart := pColorStart;
ColorEnd := pColorEnd;
FillColor1 := pFill1;
FillColor2 := pFill2;
InvertedColorTable := false;
end;
p := ptr(ord4(p) + SizeOf(PaletteHeader));
BlockMove(p, @RedLut, nColors);
p := ptr(ord4(p) + nColors);
BlockMove(p, @GreenLut, nColors);
p := ptr(ord4(p) + nColors);
BlockMove(p, @BlueLut, nColors);
ReleaseResource(LutH);
end;
end;
procedure DrawScale;
var
hloc, vloc, width, height, SaveForeground, LUTStart, LutEnd, LUTWidth: integer;
SaveGDevice: GDHandle;
begin
if NoSelection or NotRectangular then
exit(DrawScale);
ShowWatch;
with info^.RoiRect, info^ do begin
width := right - left;
height := bottom - top;
if (width = 0) or (height = 0) then
exit(DrawScale);
SaveGDevice := GetGDevice;
SetGDevice(osGDevice);
SetPort(GrafPtr(osPort));
PenNormal;
SetupUndoFromClip;
SetupUndo;
WhatToUndo := UndoEdit;
SaveForeground := ForegroundIndex;
LUTStart := ColorStart;
if LutStart <= 0 then
LutStart := 1;
LutEnd := ColorEnd;
if LutEnd >= 255 then
LutEnd := 254;
LUTWidth := LutEnd - LutStart + 1;
if width >= height then
for hloc := left to right - 1 do begin
SetForegroundColor(trunc(((hloc - left) / width) * LUTWidth) + LUTStart);
MoveTo(hloc, top);
LineTo(hloc, Bottom - 1);
end
else
for vloc := top to bottom - 1 do begin
SetForegroundColor(trunc(((vloc - top) / height) * LUTWidth) + LUTStart);
MoveTo(left, vloc);
LineTo(right - 1, vloc);
end;
SetForegroundColor(SaveForeground);
changes := true;
end;
SetupRoiRect;
SetGDevice(SaveGDevice);
end;
procedure MakeSpectrum;
{Generates the "Spectrum" color table.}
const
Sat = -1;
Val = -1;
var
i: integer;
color: HSVColor;
begin
with info^ do begin
for i := 0 to 255 do begin
color.hue := i * 256;
color.saturation := sat;
color.value := val;
HSV2RGB(color, ctable[i].rgb);
end;
LutMode := ColorLut;
IdentityFunction := false;
SetupPseudocolor;
end;
end;
function GetColorTableItem (ctab: ColorTableType): integer;
begin
case ctab of
AppleDefault:
GetColorTableItem := SystemPaletteItem;
Pseudo20:
GetColorTableItem := Pseudo20Item;
Pseudo32:
GetColorTableItem := Pseudo32Item;
Rainbow:
GetColorTableItem := RainbowItem;
Fire1:
GetColorTableItem := Fire1Item;
Fire2:
GetColorTableItem := Fire2Item;
Ice:
GetColorTableItem := IceItem;
Grays:
GetColorTableItem := GraysItem;
Spectrum:
GetColorTableItem := SpectrumItem;
otherwise
GetColorTableItem := Pseudo20Item;
end;
end;
procedure SwitchColorTables (item: integer; update: boolean);
var
ok: boolean;
begin
DisableDensitySlice;
if update then
SetupLutUndo;
with info^ do begin
case item of
SystemPaletteItem: begin
ok := LoadCLUTResource(AppleDefaultCLUT);
ColorTable := AppleDefault;
end;
Pseudo20Item: begin
GetLutResource(Pseudo20ID);
ColorTable := Pseudo20;
end;
Pseudo32Item: begin
GetLutResource(Pseudo32ID);
ColorTable := Pseudo32;
end;
RainbowItem: begin
GetLutResource(RainbowID);
ColorTable := Rainbow;
end;
Fire1Item: begin
GetLutResource(Fire1ID);
ColorTable := Fire1;
end;
Fire2Item: begin
GetLutResource(Fire2ID);
ColorTable := Fire2;
end;
IceItem: begin
GetLutResource(IceID);
ColorTable := Ice;
end;
GraysItem: begin
GetLutResource(GraysID);
ColorTable := Grays;
end;
SpectrumItem:
if ControlKeyDown and OptionKeyDown and ShiftKeyDown then
SaveLutResource
else begin
MakeSpectrum;
ColorTable := Spectrum;
end;
end; {case}
LutMode := Pseudocolor;
if update then begin
UpdateLUT;
UpdateMap;
end;
end;
end;
procedure SetNumberOfColors (n: integer);
var
i, r, g, b, index: integer;
eIndex, inc, fraction: extended;
SaveRed, SaveGreen, SaveBlue: LutArray;
begin
with info^ do begin
SaveRed := RedLUT;
SaveGreen := GreenLUT;
SaveBlue := BlueLUT;
eIndex := 0.0;
inc := (nColors - 1) / (n - 1);
for i := 0 to n - 1 do begin
index := trunc(eIndex);
if index >= (nColors - 1) then begin
RedLUT[i] := SaveRed[index];
GreenLUT[i] := SaveGreen[index];
BlueLUT[i] := SaveBlue[index]
end
else begin
fraction := eIndex - index;
RedLUT[i] := round(SaveRed[index] * (1.0 - fraction) + SaveRed[index + 1] * fraction);
GreenLUT[i] := round(SaveGreen[index] * (1.0 - fraction) + SaveGreen[index + 1] * fraction);
BlueLUT[i] := round(SaveBlue[index] * (1.0 - fraction) + SaveBlue[index + 1] * fraction);
end;
eIndex := eIndex + inc;
end;
nColors := n;
LutMode := PseudoColor;
ColorTable := CustomTable;
UpdateLUT;
UpdateMap;
end;
end;
procedure SetNumberOfExtraColors;
var
n: integer;
Canceled: boolean;
begin
n := GetInt('Number of Extra Colors(0..6):', nExtraColors, Canceled);
if (n <= 6) and (n >= 0) and not Canceled then begin
nExtraColors := n;
RedrawLUTWindow;
SelectWindow(LUTWindow);
if info <> NoInfo then
SelectWindow(info^.wptr);
end
else if not Canceled then
beep;
end;
procedure DoLutOptions;
const
nColorsID = 7;
nExtraColorsID = 8;
InvertID = 9;
var
mylog: DialogPtr;
item, i, n, nExtra: integer;
InvertLut: boolean;
begin
with info^ do begin
InitCursor;
mylog := GetNewDialog(210, nil, pointer(-1));
n := nColors;
SetDNum(MyLog, nColorsID, n);
nExtra := nExtraColors;
SetDNum(MyLog, nExtraColorsID, nExtra);
InvertLut := false;
SetDlogItem(mylog, InvertID, ord(InvertLut));
repeat
ModalDialog(nil, item);
if item = nColorsID then
n := GetDNum(MyLog, nColorsID);
if item = nExtraColorsID then
nExtra := GetDNum(MyLog, nExtraColorsID);
if item = InvertID then begin
InvertLut := not InvertLut;
SetDlogItem(mylog, InvertID, ord(InvertLut));
end;
until (item = ok) or (item = cancel);
DisposeDialog(mylog);
if item = cancel then
exit(DoLutOptions);
DisableDensitySlice;
SetupLutUndo;
if n < 1 then
n := 1;
if n > 256 then
n := 256;
if n <> nColors then
SetNumberOfColors(n);
if (nExtra <> nExtraColors) and (nExtra >= 0) and (nExtra <= 6) then begin
nExtraColors := nExtra;
RedrawLUTWindow;
SelectWindow(LUTWindow);
if info <> NoInfo then
SelectWindow(info^.wptr);
end;
if InvertLut then begin
InvertPalette;
UpdateLut;
if ScreenDepth <> 8 then
DrawLUT;
end;
end; {with info}
end;
function SetupMask: boolean;
{Creates a mask in the undo buffer for operating}
{on non-rectangular selections .}
var
tPort: GrafPtr;
SaveInfo: InfoPtr;
SaveGDevice: GDHandle;
begin
if NoUndo then begin
SetupMask := false;
exit(SetupMask)
end;
SetupUndoInfoRec;
SaveInfo := Info;
Info := UndoInfo;
SaveGDevice := GetGDevice;
SetGDevice(osGDevice);
GetPort(tPort);
with Info^ do begin
SetPort(GrafPtr(osPort));
pmForeColor(BlackIndex);
pmBackColor(WhiteIndex);
PenNormal;
EraseRect(RoiRect);
PaintRgn(roiRgn);
end;
SetPort(tPort);
SetGDevice(SaveGDevice);
Info := SaveInfo;
SetupMask := true;
end;
procedure ApplyTableToLine (data: ptr; var table: LookupTable; width: LongInt);
{$IFC PowerPC}
var
line: LinePtr;
i: integer;
begin
line := LinePtr(data);
for i := 0 to width - 1 do
Line^[i] := table[band(Line^[i],255)];
end;
{$ELSEC}
{a0 = data}
{a1 = lookup table}
{d0 = width }
{d1 = pixel value}
inline
$4E56, $0000, { link a6,#0}
$48E7, $C0C0, { movem.l a0-a1/d0-d1,-(sp)}
$206E, $000C, { move.l 12(a6),a0}
$226E, $0008, { move.l 8(a6),a1}
$202E, $0004, { move.l 4(a6),d0}
$5380, { subq.l #1,d0}
$4281, { clr.l d1}
$1210, {L move.b (a0),d1}
$10F1, $1000, { move.b 0(a1,d1.w),(a0)+}
$51C8, $FFF8, { dbra d0,L}
$4CDF, $0303, { movem.l (sp)+,a0-a1/d0-d1}
$4E5E, { unlk a6}
$DEFC, $000C; { add.w #12,sp}
{$ENDC}
procedure PutLineUsingMask (h, v, count: integer; var line: LineType);
var
aLine, MaskLine: LineType;
i: integer;
SaveInfo: InfoPtr;
begin
if count > MaxLine then
count := MaxLine;
GetLine(h, v, count, aline);
SaveInfo := Info;
Info := UndoInfo;
GetLine(h, v, count, MaskLine);
for i := 0 to count - 1 do
if MaskLine[i] = BlackIndex then
aLine[i] := line[i];
info := SaveInfo;
PutLine(h, v, count, aLine);
end;
procedure ApplyTable(var table: LookupTable);
var
width, NumberOfLines, i, hloc, vloc: integer;
offset: LongInt;
p: ptr;
UseMask: boolean;
TempLine: LineType;
AutoSelectAll: boolean;
begin
if NotInBounds then
exit(ApplyTable);
AutoSelectAll := not Info^.RoiShowing;
if AutoSelectAll then
SelectAll(false);
if TooWide then
exit(ApplyTable);
ShowWatch;
with info^.RoiRect, info^ do begin
if RoiType <> RectRoi then
UseMask := SetupMask
else
UseMask := false;
SetupUndoFromClip;
WhatToUndo := UndoTransform;
offset := top * BytesPerRow + left;
if UseMask then
p := @TempLine
else
p := ptr(ord4(PicBaseAddr) + offset);
width := right - left;
NumberOfLines := bottom - top;
hloc := left;
vloc := top;
end;
if width > 0 then
for i := 1 to NumberOfLines do
if UseMask then begin
GetLine(hloc, vloc, width, TempLine);
ApplyTableToLine(p, table, width);
PutLineUsingMask(hloc, vloc, width, TempLine);
vloc := vloc + 1
end
else begin
ApplyTableToLine(p, table, width);
p := ptr(ord4(p) + info^.BytesPerRow);
end;
with info^ do begin
UpdateScreen(RoiRect);
Info^.changes := true;
end;
SetupRoiRect;
if AutoSelectAll then
KillRoi;
end;
procedure FixColors;
{Because NIH Image always sets LUT entries 0 and 255 to white and black respectively we need to map}
{pixels with values of 0 or 255 to the nearest matching color in the other 254 LUT entries.}
var
i, match0, match255: integer;
table: LookupTable;
procedure BestMatch (index1: integer; var match: integer);
var
i, index2: integer;
rdiff, gdiff, bdiff, r1, g1, b1: LongInt;
diff, mindiff: extended;
begin
match := index1;
mindiff := 10e10;
if index1 = 0 then
index2 := 1
else
index2 := 254;
with info^ do begin
r1:=band(bsr(cTable[index1].rgb.red, 8),255);
g1:=band(bsr(cTable[index1].rgb.green, 8),255);
b1:=band(bsr(cTable[index1].rgb.blue, 8),255);
for i := 1 to 254 do begin
rdiff := r1 - band(bsr(cTable[index2].rgb.red, 8),255);
gdiff := g1 - band(bsr(cTable[index2].rgb.green, 8),255);
bdiff := b1 - band(bsr(cTable[index2].rgb.blue, 8),255);
diff := sqrt(sqr(rdiff) + sqr(gdiff) + sqr(bdiff));
if diff < mindiff then begin
match := index2;
mindiff := diff;
end;
if index1 = 0 then
index2 := index2 + 1
else
index2 := index2 - 1;
end; {for}
end; {with}
end;
begin
BestMatch(0, match0);
BestMatch(255, match255);
table[0] := match0;
for i := 1 to 254 do
table[i] := i;
table[255] := match255;
ApplyTable(table);
end;
end.